package com.base.commons.tools.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.concurrent.FutureCallback;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.CompletableFuture;

@Slf4j
public class FbgFutureCallback<T> implements FutureCallback<T>{

    private T response;

    private AsyncHttpClients asyncHttpClients;

    private CompletableFuture future;

    private String url;

    private List<String> headerKeys;
    /**
     * 申明异步回调的时候添加记录开始时间
     */
    private long startTime;

    private Span parentSpan;

    public FbgFutureCallback(AsyncHttpClients asyncHttpClients,CompletableFuture future,String url){
        //业务代码
        this.startTime  = System.nanoTime();
        this.asyncHttpClients = asyncHttpClients;
        this.future = future;
        this.url = url;
    }

    public FbgFutureCallback(AsyncHttpClients asyncHttpClients, CompletableFuture future, String url, List<String> headerKeys){
        //业务代码
        this.startTime  = System.nanoTime();
        this.asyncHttpClients = asyncHttpClients;
        this.future = future;
        this.url = url;
        this.headerKeys = headerKeys;
    }

    public void setSpan(Span span){
        this.parentSpan = span;
    }

    @Override
    public void completed(T response) {
        Tracer tracer = GlobalTracer.get();
        // 创建span
        Span span = tracer.buildSpan("completed").asChildOf(this.parentSpan).start();
        try (Scope ignored = tracer.activateSpan(span)) {
            tracer.activeSpan();
            //业务代码
            try {
                String plain = asyncHttpClients.responseForPlain("utf-8", (HttpResponse)response);
                log.info("url:{} request is success, cost time: {}ms, result:{}", url,(System.nanoTime()-startTime)/1000/1000,plain);

                JSONObject json = JSON.parseObject(plain, Feature.OrderedField);
                JSONObject headerJson = null;
                if(!CollectionUtils.isEmpty(headerKeys)){
                    headerJson = asyncHttpClients.getResponseHeaders((HttpResponse)response,headerKeys);
                    if(!headerJson.isEmpty()){
                        String dataKey = "Data";
                        JSONObject dataJson = json.getJSONObject(dataKey);
                        if(dataJson==null){
                            dataKey = "data";
                            dataJson = json.getJSONObject(dataKey);
                        }
                        if(dataJson!=null){
                            dataJson.putAll(headerJson);
                            json.put(dataKey,dataJson);
                        }
                    }
                }
                future.complete(json);
            } catch (Exception e) {
                log.error("read response is exception.", e);
                future.completeExceptionally(e);
            }
        } catch (Exception e) {
            TracingHelper.onError(e, span);
        } finally {
            span.finish();
            parentSpan.finish();
        }
    }

    @Override
    public void failed(Exception ex) {
        Tracer tracer = GlobalTracer.get();
        // 创建span
        Span span = tracer.buildSpan("failed").asChildOf(this.parentSpan).start();
        try (Scope ignored = tracer.activateSpan(span)) {
            //业务代码
            int responseCode = 0;
            if(response!=null){
                responseCode = ((HttpResponse)response).getStatusLine().getStatusCode();
            }
            log.error("url:{} request is failed, cost time: {}ms, statusCode:{}.", url,(System.nanoTime()-startTime)/1000/1000 ,responseCode,ex);
            future.completeExceptionally(ex);
        } catch (Exception e) {
            TracingHelper.onError(e, span);
        } finally {
            span.finish();
            parentSpan.finish();
        }
    }

    @Override
    public void cancelled() {
        Tracer tracer = GlobalTracer.get();
        // 创建span
        Span span = tracer.buildSpan("canceled").asChildOf(this.parentSpan).start();
        try (Scope ignored = tracer.activateSpan(span)) {
            //业务代码
            log.error("url:{} request is canceled, cost time: ｛｝ms",url,(System.nanoTime()-startTime)/1000/1000);
            future.cancel(true);
        } catch (Exception e) {
            TracingHelper.onError(e, span);
        } finally {
            span.finish();
            parentSpan.finish();
        }
    }
}
